/*
===========================================================================================
本文件应该使用 .JS 扩展名,方便 CMD+CLICK 文本中的 URL.
===========================================================================================

请在无尘环境中洗干净手用RMBP.AS.

输入法 百度强一些
搜狗...你选择了几个字,然后要打字直接替换这几个字的话.有问题...

阅读文档的方法:请熟练使用 as.TODO.以快速找到感兴趣的内容.

无论是哪个 OS/语言 的IDE,都应该始终维护一份根目录下的README,作为该操作系统及语言的知识库起点.
其中应该包括操作系统使用技巧和开发语言的相关知识.
如果内容过多就01,02,03.必要时可以通过 TODO 形成索引.

===========================================================================================
TODO:android 开发概述
===========================================================================================
相比 xcoden,as 编译时 CPU 的负担很重.而且很慢.
接电源使用 as 貌似比不接电源的速度快很多.

不过 as 的编辑功能非常强大.速度极快.
提供了大量的非常人性化的编辑功能.
作为 IDE 来说非常优秀.
至于编译问题,这是 java 语言的天生劣势...
看起来真有可能有一天谷歌会转用 swift 语言吧.

===========================================================================================
安装 homebrew + gradle
===========================================================================================
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
brew install gradle

git init
git add .
git commit -m “ Initial Commit”

===========================================================================================
TODO:apple vs google:
===========================================================================================
Q:iPhone 6 性价比不如 荣耀6.有啥好?
A:
1.逼格高.IOS代表天界.安卓代表妖怪.
2.性能高.硬件配置较低就能跟安卓竞争.
2.安卓整体粗糙.耗CPU+电池
3.软件精致,用户省心.

阿修罗的安卓.善意和谦卑.方便的快捷键.
天人的ios.恶意和鄙视.不喜欢快节奏.

项目.MODULE.gradle.
项目文档结构凌乱 其实只需要关注:manifest.res.*.java

在 MyApplication 开始处编写代码效率就已经极高. testcode 模块没有存在的意义.

没动力开发安卓app?
1 也无非就是功耗嘛.接上ac电源,怕什么?
2 给我们自己作app...
3 MyApplication.start.coding.test.

===========================================================================================
入门:
===========================================================================================
TODO:as 快捷键
多如牛毛.各种方便无数
XCODE 比较反人类,所以主要是与 XCODE 中对比:

翻页:FN+上下:光标位置一并改变.IOS 差
剪切:CTRL+X:支持全部剪切方式.IOS 差

删除当前行
    AS.CMD+X.
    IOS.只能自定义快捷键(CMD+D)

格式整理:
    AS.CMD+ALT+L
    IOS:只能整理选中行的缩进.CMD+|

缩放字体:
    AS:CMD+MOUSE SCROLL UP
    IOS:无

查找当前选中的内容:
    AS.CMD+F 或者 CMD+SHIFT+F(整个工作空间)
    IOS.无.只能自定义快捷键,比如:CMG+ALT+G.

替换:
    AS:CMD+R
    IOS:CMD+SHIFT+F

折叠全部文件目录:
    AS.专用按钮
    IOS.ALT+LEFT/RIGHT.

在项目树中定位当前打开的文件
    AS.专用按钮
    IOS.右键菜单中找

跳转到文件头部:CMD+上下
跳转到上一位置:CMD+[

查找引用:
    AS.ALT+F7
    IOS.右键菜单中找

运行:
    AS:CTRL+D
    IOS:CMD+R

查看当前代码所在的方法名称:
    AS:CMD+F12
    IOS:顶部工具栏有

选择最近打开的文件:
    AS:CMD+E
    IOS:顶部工具栏有

自动修正当前错误:
    AS:ALT+ENTER
    IOS:CTL+ALT+CMD+F

OVERRIDE METHOD:
    AS:CTL+O
    IOS:好像没有...

显示指定方法的说明
    AS:F1
    IOS:ALT + CLICK

===========================================================================================
TODO:java 中的重量级概念:
===========================================================================================
抽象类
普通类 + abstract 关键字.
它是一个不完整的类.所有的方法都只有定义,没有实现.
方法的实现留给了抽象类的使用者.new xxx(){…}.用于方便地实现其中的抽象方法
在AB框架中很常见.

接口
interface 只是定义了一组无内容的方法.也可以new xxx(){….}
用于将不同类型的东西强制划归为同类.

线程
Thread 纯粹就是为了解决主线程繁忙的问题.利用多核心 CPU 提供高品质的用户体验.
new Thread(){}.start();//^O(run)
AsyncTask 类似.而且更好,因为它可以直接操作UI线程...

消息处理
Handler(MSG) 自定义的消息处理机制.
但安卓之中仅用于解决在线程中刷新UI元素的问题.
因为线程中是禁止直接处理UI元素的,所以要用Handler转发一下.
所有,有了AsyncTask,消息处理其实用处就有限了.

* android 的事件处理机制
* http://www.cnblogs.com/mengdd/p/3394345.html
*
* [dispatchTouchEvent].MotionEvent.ACTION_MOVE:
* [onTouchEvent].MotionEvent.ACTION_MOVE:

资源文件
res 对于开发者的意义:相当于是appface...
支持内部嵌套引用.比如:
colors:#333333
dimens:88dp
strings:”…”
id:”abc”

===========================================================================================
怪异的android语句:
if (“abc”.equals(“abc”)){
//…
//…
//…
}

TODO:经典的 android 语句:
BitMap b = BitmapFactory.decodeResource(
MyApplication.getInstance().getResources(),
R.drawable.btncheck_no
);

另外如果你想setTag(a,b),那么a就必须是一个声明过的整数…专用的整数…

点9图:
http://www.cnblogs.com/tijing/archive/2012/08/23/2652177.html

==========================================================================================
TODO:调用相机/相册以及 ContentResolver:
INTENT 打开一个系统页面,等待返回.
如果拍照时想显示一个"水印"就得自己做了,不能调用系统页面....

拍照就返回拍好的照片.
选图就返回一个图片多选的数组.(但实际上是没有多选这个选项??)

拍照:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera, 8888);

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap)bundle.get("data");
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
}

选图:
Intent picture = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(picture, PICTURE);

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Uri selectedImage = data.getData();
String[] filePathColumns = {MediaStore.Images.Media.DATA};
Cursor c = this.getContentResolver().query(selectedImage, filePathColumns, null,null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePathColumns[0]);
String picturePath= c.getString(columnIndex);
c.close();
}

ContentResolver.查询条件.写法:
    getContentResolver().query(...)
        Cursor cursor=getContentResolver().query(
        Phones.CONTENT_URI,
        null,
        Phones.NUMBER+" LIKE"+" '%"+ text +"%'"+" OR "+Phones.NAME+" LIKE"+" '%"+text+"%'",
        null,
        null
    );

查出所有的系统缩略图:
    {
        ContentResolver cr = getContentResolver();
        String[] cols = {
                Thumbnails._ID,
                Thumbnails.IMAGE_ID,// == images._id
                Thumbnails.DATA
        };

        //*****
        Cursor cur = cr.query(
                Thumbnails.EXTERNAL_CONTENT_URI,
                cols,
                null, null, null);

        assert cur != null;

        ArrayList<HashMap<String, String>> list = new ArrayList<>();

        int _id;
        int image_id;
        String image_path;

        int _idColumn = cur.getColumnIndex(Thumbnails._ID);
        int image_idColumn = cur.getColumnIndex(Thumbnails.IMAGE_ID);
        int dataColumn = cur.getColumnIndex(Thumbnails.DATA);

        while (cur.moveToNext()) {
            // Get the field values
            _id = cur.getInt(_idColumn);
            image_id = cur.getInt(image_idColumn);
            image_path = cur.getString(dataColumn);

            // Do something with the values.
            println.i(_id + " image_id:" + image_id + " path:"
                    + image_path + "---");

            HashMap<String, String> hash = new HashMap<>();
            hash.put("image_id", image_id + "");
            hash.put("path", image_path);
            list.add(hash);

        }

        cur.close();

        println.i(list.size() + "");
    }

===========================================================================================
CWY@2016-07-28 15:36:07
TODO:关于消息推送
当 APP 需要集成消息推送功能时,首先担心消息是否总是能够被接收到.
手机本身有短信功能,只要连接到电信移动网络就可以确保收到短信.不需要连接互联网.
但是要想收到APP推送的消息,移动设备还必须连接互联网.
而互联网终究也是电信移动运营商的服务.

这样就需要两道关口才行.首先有电信移动网络,其次连接了互联网.
所以APP消息推送的可靠性在理论上最多只有手机短信的一半
只是由于短信几乎百分百可靠,所以APP可靠性才与运营商基本无关.

那么理论上消息推送的可靠性最多能达到用户移动设备的互联网可靠性.
断网就不可能收到推送消息了.

移动设备的操作系统供应商都提供了统一的消息推送方案
但是由于安卓设备的操作系统提供商谷歌与天朝决裂,所以安卓设备就没有统一方案(GCM)了.
这后果就是,安卓设备中安装的APP需要各自解决它们的消息推送问题.

最标准做法就是与服务器建立持久连接
这样安卓设备中就会每个APP都建立一个持久连接.而不是统一使用一个持久连接.

Q 用户无法知道哪些 APP 正在运行.这在 PC 上是不可思议的事.
A 用户可以认为只有当前屏幕显示的 APP 是正在运行的.

Q:如何做到消息推送?
A:APP.SERVICE...
A:BOOT.ACTION_BOOT_COMPLETED广播.APP.MANIFEST.捕获该广播的权限.BroadcastReceiver.启动Activity/Service，

问 每次开机伴随着大量服务启动?浪费电啊
答 把耗电多的APP卸载.

由于不可靠而导致的复杂性,出现了第三方提供消息推送服务.
以下我们只讨论极光推送这个第三方服务.

一个安卓APP要依赖于极光推送服务,就需要在APP中调用极光推送的类库,如下图所示:
http://git.oschina.net/cleanland/IMAGES/raw/master/oop.png

要加入的东西很多.这就是之前提到的复杂性引起的恶果.
1,要复制一堆文件到项目中
2,要修改 MANIFEST 和 GRADLE 文件
3,要修改启动方法,加入 JPUSH 有关的内容.

第三方系统收不到推送的消息:
由于第三方 ROM 的限制,而需要用户手动操作:
小米【MIUI】
自启动管理：需要把应用加到【自启动管理】列表，否则杀进程或重新开机后进程无法开启
通知栏设置：应用默认都是显示通知栏通知，如果关闭，则收到通知也不会提示
网络助手：可以手动禁止已安装的第三方程序访问2G/3G和WIFI的网络和设置以后新安装程序是否允许访问2G/3G和WIFI的网络
MIUI 7 神隐模式： 允许应用进行自定义配置模式，应用在后台保持联网可用，否则应用进入后台时，应用无法正常接收消息。
【设置】下电量和性能中【神隐模式】

华为【Emotion】
自启动管理：需要把应用加到【自启动管理】列表，否则杀进程或重新开机后进程不会开启，只能手动开启应用
后台应用保护：需要手动把应用加到此列表，否则设备进入睡眠后会自动杀掉应用进程，只有手动开启应用才能恢复运行
通知管理：应用状态有三种：提示、允许、禁止。禁止应用则通知栏不会有任何提醒

魅族【Flyme】
自启动管理：需要把应用加到【自启动管理】列表，否则杀进程或重新开机后进程无法开启
通知栏推送：关闭应用通知则收到消息不会有任何展示
省电管理： 安全中心里设置省电模式，在【待机耗电管理】中允许应用待机时，保持允许，
否则手机休眠或者应用闲置一段时间，无法正常接收消息。

针对特定设备推送消息:
1,在 APP 中向 JPUSH 发送 ALIAS 命令:JPushInterface.setAliasAndTags().
2,向 APP.SERVER 发送 ALIAS 命令.
3,SERVER 向 JPUSH 发推送消息命令.指定 ALIAS.

===========================================================================================
2015-06-24 09:20:35
TODO:服务
1.至少可以从页面中启动一个服务...
intent = new Intent("com.monitor.service");
startService(intent);//开启服务

2.config.service
<service
android:name=".MonitorService"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="com.monitor.service" />
</intent-filter>
</service>
3 MonitorService.onStartCommand.run().Thread.whilelooop

===========================================================================================
TODO:切换横屏
http://blog.csdn.net/jiangxinyu/article/details/8600407

===========================================================================
如果想做商业软件，必须签名，混淆，然后在正规渠道上传，可能代码中还需要自己加上一些检查手段。
而且还必须先上架ios版的。因为国内安卓市场很难推广。
但是其实混淆的意义感觉并不大.

Gradle中ProGuard的配置
By 黄云坤 2013-12-23 更新日期:2014-11-16

ProGuard是一个压缩、优化和混淆Java 字节码文件的软件。
它可以删除无用的类、字段、方法和属性。还可以删除没用的注释，优化 字节码文件。
它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。

混淆功能是将包名、类名、方法名等等用无意义的字符替换掉，可以增加反编译的难度，保护你的代码。
混淆也可以减少包的大小，但是混淆后不利于调试。

虽然目前ProGuard可以分析一些简单的情况，但是更多的时候还是需要自己配置。

在Gradle中使用ProGuard ProGuard提供了Gradle插件，这样我们可以更方便的将ProGuard集成进来了。

当前最新版是4.10。 这个插件的介绍页面我死活打不开了…主要的参考也是其他项目的配置。

先来看看如果在Gradle中生成一个独立包。这个包需要包含自身的源码、资源还有所有的第三方依赖。
如果你的项目是一个多MODEL项目，那么你的独立包还应该???其他需要的子项目，一般情况下配置如下：

===========================================================================
TODO:android 开发中的神器
Android开源项目分类汇总
https://github.com/Trinea/android-open-project

在网页上做做按钮....它可以替你生成大量的....源码啊....
http://angrytools.com/android/button/

在网页上面画流程图的神器,注册个帐号就能保存在云端了...
https://www.gliffy.com/
如果感觉网速慢,可翻墙

用句点语法将最复杂线路组织起来，所有其他路径就会变得很清楚了。不画也可以。
这样我们的软件就可以做的非常复杂………太可怕了。非常强大。
*/

/*
CWY@2016-07-29 15:57:49
TODO:安卓开发的硬伤:
=================================================================
安卓非常依赖 CONTEXT.
但是你不能从一个 Application(单例) 中创建它.
只能从某个 ACTIVITY 创建!我了个去!

So just to sum things up in case someone else has the same question.
You cannot launch a dialog from the application's context
but can launch it from the Activities context.
If want a similar looking effect to a dialog then you can
create an activity that uses the dialog theme and launch that
with startActivity using the applications context.
– w.donahue Feb 12 '11 at 20:11 STACKOVERFLOW!

=================================================================
你基本上不可能100%的拿到当前正在运行的 ACTIVITY...
即使是用旧方法也只能得到个类别,而不是实例!
可能新的 SDK 中会解决这问题,但是版本非常高,23之类的..
=================================================================
*/

/*
=================================================================
TODO:源代码管理 GIT...
=================================================================
在项目中增加一个专门管理 DOC 的跨项目文件夹:
原理:在项目中增加一个文件夹,并将它关联到 OSCHINA 上的现有项目...
1 create a project on https://git.oschina.net
1 open a project in AS IDE.
2 vcs/import into version control/create git repo...
3 vcs/checkout from version control/git
3.1 paste the git url of the oschina project.
3.2 set path of the git project to a AS project's subfolder
4.需要 GIT RESET HEAD,否则报 AS 内部错误...说明没多少人做这种事情.

OK.
will create a new folder under the 3.2 path.


=================================================================
TODO:DEBUG 技巧
=================================================================
DEBUG TOOLE WINDOW..console is much better then the Android Monitor tool window.

* */

